package be.dch.objectprops.parser;

import java.lang.reflect.Array;
import java.lang.reflect.Field;

import org.apache.log4j.Logger;

import be.dch.objectprops.ParserFinder;
import be.dch.objectprops.collector.Collector;
import be.dch.util.ArrayUtils;

import com.google.inject.Inject;

public class ArrayParser implements Parser {

    private static final Logger LOG = Logger.getLogger(ArrayParser.class);
    @Inject
    private transient Collector props;

    @Inject
    private transient ParserFinder finder;

    public boolean handleAsWriter(final Object result) {
	ArrayParser.LOG.debug("Investigating of object can be handled");
	return result.getClass().isArray();
    }

    public boolean handleAsReader(final Field field) {
	if (field == null) {
	    return false;
	}
	Class<?> clazz = field.getType();
	return clazz.isArray();
    }

    public void write(final Object result, final StringBuilder key) {
	final int length = Array.getLength(result);
	final int keyLength = key.toString().length();
	for (int j = 0; j < length; j++) {
	    key.setLength(keyLength);
	    key.append('.');
	    key.append(j);
	    final Object arrayObject = Array.get(result, j);
	    if (arrayObject != null) {
		this.finder.write(arrayObject, key);
	    }
	}

    }

    public void read(final StringBuilder key, final Field array, final Object result) {
	final int initialLength = key.length();
	final String clazzName = array.getType().getName().replaceAll("\\[L", "").replaceAll(";", "");
	int j = 0;
	key.setLength(initialLength);
	key.append('.');
	key.append(j);
	Object[] targetArray = null;
	try {
	    targetArray = (Object[]) Array.newInstance(Class.forName(clazzName), 0);
	} catch (final ClassNotFoundException e) {
	    LOG.error(e);
	}
	while (this.props.startWithKey(key.toString())) {
	    LOG.debug("Analysing array of " + clazzName + " with prefix " + key.toString());

	    Object arrayObject = null;
	    try {
		arrayObject = Class.forName(clazzName).newInstance();
	    } catch (final ClassNotFoundException e) {
		LOG.error(e);
	    } catch (final InstantiationException e) {
		LOG.error(e);
	    } catch (final IllegalAccessException e) {
		LOG.error(e);
	    }
	    arrayObject = this.finder.read(key, arrayObject);
	    LOG.debug("adding to array: " + arrayObject.toString());

	    targetArray = ArrayUtils.add(targetArray, arrayObject);
	    j++;
	    key.setLength(initialLength);
	    key.append('.');
	    key.append(j);
	}
	try {
	    array.set(result, targetArray);
	} catch (final IllegalArgumentException e) {
	    ArrayParser.LOG.error(e);
	} catch (final IllegalAccessException e) {
	    ArrayParser.LOG.error(e);
	}
	key.setLength(initialLength);

    }

    public Object read(final StringBuilder key, final Object result) {
	return null;
    }

    protected void setProps(Collector props) {
	this.props = props;
    }
    
    protected void setFinder(ParserFinder finder) {
	this.finder = finder;
    }

}
